#pragma once

#include <iostream>
#include <string>
#include <cstring>
#include <ctype.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <netinet/in.h>
#include <jsoncpp/json/json.h>
using namespace std;

#define SEP " "
#define SEP_LINE strlen(SEP)
#define LINE_SEP "\r\n"
#define LINE_SEP_LINE strlen(LINE_SEP)

enum
{
    OK = 0,
    DIV_ERR,
    MOD_ERR,
    OP_ERR, // 代表运算填写错误
};

// 添加协议报头  "x + y"  ->  "content_line"\r\n"x + y"\r\n
string enLength(const string &requst)
{
    string send_string = to_string(requst.size());
    send_string += LINE_SEP;
    send_string += requst;
    send_string += LINE_SEP;

    return send_string;
}

// 去掉协议报头   "content_line"\r\n"exitCode result"\r\n  ->  "exitCode result"
bool deLength(const string &package, string *text)
{
    auto pos = package.find(LINE_SEP);
    if (pos == string::npos)
    {
        return false;
    }

    string text_length_str = package.substr(0, pos);
    int text_length = stoi(text_length_str);
    *text = package.substr(pos + LINE_SEP_LINE, text_length);

    return true;
}

// 从一堆报文中获取至少一个有效报文  "content_len"\r\n"x op y"\r\n"content_len"\r\n"x op y"\r\n
bool recvPackage(int sock, string &inbuffer, string *text)
{
    char buffer[1024];
    while (1)
    {
        // 采用recv接口
        ssize_t n = recv(sock, buffer, sizeof(buffer) - 1, 0);
        if (n > 0)
        {
            // 成功读取
            buffer[n] = 0;
            inbuffer += buffer;
            auto pos = inbuffer.find(LINE_SEP);
            if (pos == string::npos)
            {
                // 没有读到一个有效报文
                continue;
            }

            string text_len_string = inbuffer.substr(0, pos);
            int text_len = stoi(text_len_string);
            int total_len = text_len_string.size() + text_len + LINE_SEP_LINE * 2;
            cout << "处理前的报文 #inbuffer# 中的数据为:  " << inbuffer << endl;

            if (inbuffer.size() < total_len)
            {
                cout << "你输入的消息，没有严格遵守我们定制的协议，正在等待后续你再次输入的数据(continue): " << endl;
                continue;
            }
            // 至少有一个有效的报文了
            *text = inbuffer.substr(0, total_len);
            inbuffer.erase(0, total_len);
            cout << "提取有效报文后的 #inbuffer# 中的数据为:  " << inbuffer << endl;

            break;
        }
        else
        {
            return false; // 客户端退出
        }
    }

    return true;
}

class Request // 客户端发的数据
{
public:
    Request()
    {
    }

    Request(int x, int y, char op)
        : _x(x), _y(y), _op(op)
    {
    }

    // 序列化  结构化对象 -》 "x + y"
    bool Serialize(string *out)
    {
#ifdef MYSEF
        // 初始化
        *out = "";
        string x_string = to_string(_x);
        string y_string = to_string(_y);
        *out += x_string;
        *out += SEP;
        *out += _op;
        *out += SEP;
        *out += y_string;
#else
    Json::Value root;
    root["first"] = _x;
    root["second"] = _y;
    root["oper"] = _op;

    Json::FastWriter writer;
    *out = writer.write(root);

#endif
        return true;
    }

    // "x + y" -> 结构化对象  1 + 1
    bool deSerialize(const string &in)
    {
#ifdef MYSEL
        auto left = in.find(SEP);
        auto right = in.rfind(SEP);
        if (left == string::npos || right == string::npos)
        {
            return false;
        }
        if (left == right)
        {
            return false;
        }
        if (right - (left + SEP_LINE) != 1)
        {
            return false;
        }

        string x_string = in.substr(0, left);
        string y_string = in.substr(right + SEP_LINE); // 截到末尾
        if (x_string.empty())
        {
            return false;
        }
        if (y_string.empty())
        {
            return false;
        }

        _x = stoi(x_string);
        _y = stoi(y_string);
        _op = in[left + SEP_LINE];

#else
        Json::Value root;
        Json::Reader reader;
        reader.parse(in, root);

        _x = root["first"].asInt();
        _y = root["second"].asInt();
        _op = root["oper"].asInt();

#endif
        return true;
    }

public:
    int _x;
    int _y;
    char _op;
};

class Response
{
public:
    Response()
    {
    }

    Response(int exitCode, int result)
        : _exitCode(exitCode), _result(result)
    {
    }

    // 序列化  结构化 -》 "exitCode result"
    bool Serialize(string *out)
    {
#ifdef MYSEL
        *out = "";
        string codeString = to_string(_exitCode);
        string resultString = to_string(_result);

        *out += codeString;
        *out += SEP;
        *out += resultString;
#else
        Json::Value root;
        root["exitCode"] = _exitCode;
        root["result"] = _result;

        Json::FastWriter writer;
        *out = writer.write(root);
#endif

        return true;
    }
    // 反序列化
    bool deSerialize(const string &in)
    {
#ifdef
        auto mid = in.find(SEP);
        if (mid == string::npos)
        {
            return false;
        }

        string code = in.substr(0, mid);
        string res = in.substr(mid + SEP_LINE);
        if (code.empty() || res.empty())
        {
            return false;
        }

        _exitCode = stoi(code);
        _result = stoi(res);
#else
        Json::Vaule root;
        Json::Reader reader;
        reader.parse(in, root);

        _exitCode = root["exitCode"].asInt();
        _result = root["result"].asInt();
#endif

        return true;
    }

public:
    int _exitCode; // 退出码 判断是否出现异常
    int _result;   // 运算结果
};